// Package repository internal/repository/department_repository.go
package repository

import (
	"errors"
	"gorm.io/gorm"
	"gozrd-admin-api/internal/entity/model"
	"time"
)

var (
	DeptExist = errors.New("部门名称已存在")        // 导出常量
	DeptInUse = errors.New("部门正在被用户使用，无法删除") // 导出常量
)

// IDepartmentRepository 部门数据库接口
type IDepartmentRepository interface {
	GetSysDeptList(deptName string, deptStatus string) ([]model.SysDept, error)
	GetSysDeptByName(deptName string) (model.SysDept, error)
	CreateSysDept(sysDept model.SysDept) error
	GetSysDeptById(id int) (model.SysDept, error)
	UpdateSysDept(dept model.SysDept) (model.SysDept, error)
	DeleteSysDeptById(id int) error
	QuerySysDeptList() ([]model.SysDept, error) // 修改为返回模型列表
}

// DepartmentRepository 部门数据库实现
type DepartmentRepository struct {
	db *gorm.DB
}

// NewDepartmentRepository 创建部门数据库
func NewDepartmentRepository(db *gorm.DB) IDepartmentRepository {
	return &DepartmentRepository{
		db: db,
	}
}

// GetSysDeptList 查询部门列表
func (d *DepartmentRepository) GetSysDeptList(deptName string, deptStatus string) ([]model.SysDept, error) {
	var sysDepts []model.SysDept
	db := d.db.Model(&model.SysDept{})

	if deptName != "" {
		db = db.Where("dept_name = ?", deptName)
	}
	if deptStatus != "" {
		db = db.Where("dept_status = ?", deptStatus)
	}

	err := db.Find(&sysDepts).Error
	return sysDepts, err
}

// GetSysDeptByName 根据部门名称查询
func (d *DepartmentRepository) GetSysDeptByName(deptName string) (model.SysDept, error) {
	var sysDept model.SysDept
	err := d.db.Where("dept_name = ?", deptName).First(&sysDept).Error
	return sysDept, err
}

// CreateSysDept 新增部门
func (d *DepartmentRepository) CreateSysDept(sysDept model.SysDept) error {
	// 检查部门名称是否已存在
	existingDept, err := d.GetSysDeptByName(sysDept.DeptName)
	if err != nil && err != gorm.ErrRecordNotFound {
		return err
	}
	if existingDept.ID > 0 {
		return DeptExist
	}

	// 设置创建时间
	sysDept.CreateTime = time.Now()

	// 如果是公司类型，设置父ID为0
	if sysDept.DeptType == 1 {
		sysDept.ParentId = 0
	}

	// 创建部门
	return d.db.Create(&sysDept).Error
}

// GetSysDeptById 根据id查询部门
func (d *DepartmentRepository) GetSysDeptById(id int) (model.SysDept, error) {
	var sysDept model.SysDept
	err := d.db.First(&sysDept, id).Error
	return sysDept, err
}

// UpdateSysDept 修改部门
func (d *DepartmentRepository) UpdateSysDept(dept model.SysDept) (model.SysDept, error) {
	// 使用事务来确保操作的原子性
	tx := d.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询部门是否存在
	var existingDept model.SysDept
	if err := tx.First(&existingDept, dept.ID).Error; err != nil {
		tx.Rollback()
		return model.SysDept{}, err
	}

	// 更新字段
	existingDept.ParentId = dept.ParentId
	existingDept.DeptType = dept.DeptType
	existingDept.DeptName = dept.DeptName
	existingDept.DeptStatus = dept.DeptStatus

	// 保存更改
	if err := tx.Save(&existingDept).Error; err != nil {
		tx.Rollback()
		return model.SysDept{}, err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return model.SysDept{}, err
	}

	return existingDept, nil
}

// DeleteSysDeptById 删除部门
func (d *DepartmentRepository) DeleteSysDeptById(id int) error {
	// 开启事务
	tx := d.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询部门是否存在
	var dept model.SysDept
	if err := tx.First(&dept, id).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 检查部门是否被用户使用
	var count int64
	if err := tx.Model(&model.SysAdmin{}).Where("dept_id = ?", id).Count(&count).Error; err != nil {
		tx.Rollback()
		return err
	}
	if count > 0 {
		tx.Rollback()
		return DeptInUse
	}

	// 删除子部门
	if err := tx.Where("parent_id = ?", id).Delete(&model.SysDept{}).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 删除部门
	if err := tx.Delete(&model.SysDept{}, id).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return err
	}

	return nil
}

// QuerySysDeptList 查询部门列表
func (d *DepartmentRepository) QuerySysDeptList() ([]model.SysDept, error) {
	var sysDepts []model.SysDept
	err := d.db.Find(&sysDepts).Error
	return sysDepts, err
}
